using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Security.Cryptography;

namespace net.notdot.Attercop
{
    /// <summary>
    /// Encapsulates settings associated with an Attercop network.
    /// </summary>
    [Serializable()]
    public class NetworkSettings
    {
        /// <summary>
        /// The address general traffic for the network should be sent to.
        /// </summary>
        /// <remarks>
        /// Usually a Multicast address, but can be a Unicast address if a proxy is set up to relay
        /// communications when Multicast is not available.
        /// </remarks>
        public IPEndPoint NetworkAddress = new IPEndPoint(IPAddress.Parse("224.0.0.1"), 1234);

        /// <summary>
        /// The name of the encryption algorithm to use to encrypt packets, or null if encryption is not in use.
        /// </summary>
        public string EncryptionAlgorithm = null;

        /// <summary>
        /// The encryption key for the specified algorithm, or null if encryption is not in use.
        /// </summary>
        public byte[] EncryptionKey = null;

        /// <summary>
        /// The hash algorithm to use for message hashing.
        /// </summary>
        public const string MessageHashAlgorithm = "SHA1";

        /// <summary>
        /// The hash algorithm to use for file hashing
        /// </summary>
        public const string FileHashAlgorithm = "SHA1";

        public SymmetricAlgorithm GetEncryptionAlgorithm() {
            if (EncryptionKey == null || EncryptionAlgorithm == null) return null;
            SymmetricAlgorithm algo = SymmetricAlgorithm.Create(EncryptionAlgorithm);
            algo.Key = EncryptionKey;
            
            return algo;    
        }

        private TimeSpan m_HelloInterval = new TimeSpan(0, 0, 30);
        /// <summary>
        /// The frequency with which the client should send HelloMessages to
        /// the multicast channel.
        /// </summary>
        public TimeSpan HelloInterval
        {
            get
            {
                return m_HelloInterval;
            }
            set
            {
                m_HelloInterval = value;
            }
        }

        private TimeSpan m_PeerTimeout = new TimeSpan(0, 2, 0);
        /// <summary>
        /// The amount of time with no received messages before a peer should
        /// be declared 'timed out' and marked offline. Must be greater than
        /// HelloInterval.
        /// </summary>
        public TimeSpan PeerTimeout
        {
            get
            {
                return m_PeerTimeout;
            }
            set
            {
                if (TimeSpan.Compare(value, HelloInterval) < 0)
                    throw new ArgumentException("PeerTimeout must be greater than HelloInterval");

                m_PeerTimeout = value;
            }
        }

        private TimeSpan m_PeerRemove = new TimeSpan(0, 10, 0);
        /// <summary>
        /// The amount of time with no received messages before a peer should
        /// be removed from the collection of known peers. Must be greater than
        /// PeerTimeout.
        /// </summary>
        public TimeSpan PeerRemove
        {
            get
            {
                return m_PeerRemove;
            }
            set
            {
                if (TimeSpan.Compare(value, PeerTimeout) < 0)
                    throw new ArgumentException("PeerRemove must be greater than PeerTimeout");

                m_PeerRemove = value;
            }
        }

        private TimeSpan m_WindowDuration = new TimeSpan(0, 0, 5);
        /// <summary>
        /// The amount of time messages persist in the recentMessages collection. After a message is removed
        /// from the collection, no out-of-order messages with a lower sequence ID will be processed.
        /// </summary>
        /// <remarks>
        /// Setting this value lower results in a smaller recentMessages collection at the cost of
        /// possible lost packets. The default value should be fine for 99% of situations.
        /// </remarks>
        public TimeSpan WindowDuration
        {
            get
            {
                return m_WindowDuration;
            }
            set
            {
                m_WindowDuration = value;
            }
        }

        private TimeSpan m_PingTimeout = new TimeSpan(0, 0, 30);
        /// <summary>
        /// The maximum amount of time we will wait for a reply to a ping we sent. Pings received after the timeout
        /// are discarded.
        /// </summary>
        public TimeSpan PingTimeout
        {
            get
            {
                return m_PingTimeout;
            }
            set
            {
                m_PingTimeout = value;
            }
        }

        public NetworkSettings()
        {
            
        }
    }
}
